package com.barneyx.mshinfoplatform.web.front.info;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.barneyx.mshinfoplatform.common.ExResult;
import com.barneyx.mshinfoplatform.entity.area.AreaEntity;
import com.barneyx.mshinfoplatform.entity.enums.EEventType;
import com.barneyx.mshinfoplatform.entity.enums.EInfoState;
import com.barneyx.mshinfoplatform.entity.info.InfoEntity;
import com.barneyx.mshinfoplatform.entity.user.UserPlatformEntity;
import com.barneyx.mshinfoplatform.event.InfoAuditEvent;
import com.barneyx.mshinfoplatform.exception.InfoException;
import com.barneyx.mshinfoplatform.exception.MshException;
import com.barneyx.mshinfoplatform.exception.UserException;
import com.barneyx.mshinfoplatform.mapper.info.IInfoEntityMapper;
import com.barneyx.mshinfoplatform.service.info.IInfoEntityService;
import com.barneyx.mshinfoplatform.util.*;
import org.apache.ibatis.annotations.Delete;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/api/front/info/")
public class InfoController {

    @Resource
    private IInfoEntityService infoService;

    @Resource
    private InfoUtil.Cate infoCateUtil;


    @Resource
    private InfoUtil.Info infoUtil;

    @Resource
    private InfoUtil.Setting infoSettingUtil;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private AreaUtil areaUtil;

    @Resource
    private UserUtil userUtil;


    @GetMapping("newinfos")
    public ExResult<?> getNewInfos() throws MshException {
        List<InfoEntity> list = infoService.page(new Page<>(0, 20), new LambdaQueryWrapper<InfoEntity>()
                .eq(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                .orderByDesc(InfoEntity::getCreateAt)).getRecords();
        return ExResult.ofAuto(!list.isEmpty(), list);
    }

    @GetMapping("page")
    public ExResult<?> page(@RequestParam(value = "cateid") String cateId,
                            @RequestParam(value = "state", required = false) String state,
                            @RequestParam(value = "current", required = false, defaultValue = "0") long current,
                            @RequestParam(value = "size", required = false, defaultValue = "20") long size) {

        Page<InfoEntity> page = infoService.page(new Page<>(current, size), new LambdaQueryWrapper<InfoEntity>()
                .func(StrUtil.isBlank(state), c -> {
                    try {
                        c.allEq(MapUtil.builder(new HashMap<SFunction<InfoEntity, ?>, Object>())
                                .put(InfoEntity::getInfoCateId, cateId)
                                .put(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                                .put(InfoEntity::getState, EInfoState.PASS)
                                .build());
                    } catch (MshException e) {
                        throw new RuntimeException(e);
                    }
                })
                .func(StrUtil.isNotBlank(state) && state.equals("all"), c -> {
                    try {
                        c.in(InfoEntity::getInfoCateId, infoCateUtil.getInfoCateChildIds(cateId).toArray())
                                .allEq(MapUtil.builder(new HashMap<SFunction<InfoEntity, ?>, Object>())
                                        .put(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                                        .put(InfoEntity::getState, EInfoState.PASS)
                                        .build());
                    } catch (MshException e) {
                        throw new RuntimeException(e);
                    }
                })
                .orderByDesc(InfoEntity::getCreateAt));
        return ExResult.ofAuto(page != null, page);
    }

    @GetMapping("page-by-cate-ids")
    public ExResult<?> pageByCateIds(@RequestParam("cateIds") List<String> ids,
                                     @RequestParam(value = "current", required = false, defaultValue = "0") long current,
                                     @RequestParam(value = "size", required = false, defaultValue = "20") long size) throws MshException {
        boolean all = ids.get(0).equals("all");
        Page page = null;
        if (all) {
//            Object like_infos = redisUtil.get(areaUtil.getCurrentAreaId() + "_LIKE_INFOS");
//            if (like_infos == null) {
            page = infoService.page(new Page<>(current, size), new LambdaQueryWrapper<InfoEntity>()
                    .allEq(MapUtil.builder(new HashMap<SFunction<InfoEntity, ?>, Object>())
                            .put(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                            .put(InfoEntity::getState, EInfoState.PASS)
                            .build())
                    .orderByDesc(InfoEntity::getCreateAt));
//            redisUtil.set(areaUtil.getCurrentAreaId() + "_LIKE_INFOS", JSONObject.toJSONString(page), 60 * 5);
//            } else {
//                page = JSONObject.parseObject(like_infos.toString(), Page.class);
//            }

        } else {
            page = infoService.page(new Page<>(current, size), new LambdaQueryWrapper<InfoEntity>()
                    .allEq(MapUtil.builder(new HashMap<SFunction<InfoEntity, ?>, Object>())
                            .put(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                            .put(InfoEntity::getState, EInfoState.PASS)
                            .build())
                    .in(InfoEntity::getInfoCateId, ids).orderByDesc(InfoEntity::getCreateAt));
        }
        return ExResult.ofAuto(page != null, page);
    }


    @PostMapping("add")
    public ExResult<?> createInfo(@RequestBody InfoEntity infoData) throws MshException {
        infoSettingUtil.CheckUserIsPost(infoData.getUserId());//判断平台是否有发布限制
        infoSettingUtil.CheckInfoState(infoData); //判断是否要审核
        return ExResult.ofAuto(infoUtil.createInfo(infoData), infoData);
    }

    @PutMapping("update")
    public ExResult<?> updateInfo(@RequestBody InfoEntity infoData) throws InfoException, UserException {
        UserPlatformEntity currentLoginUserInfo = userUtil.getCurrentLoginUserInfo();
        if (!infoData.getUserId().equals(currentLoginUserInfo.getUserId()))
            throw new InfoException("错误!当前信息并不是您发布的信息!,您无权限进行操作");
        return ExResult.ofAuto(infoUtil.updateInfoBaseInfo(infoData), infoData);
    }


    @GetMapping("update-count")
    public ExResult<?> updateCount(@RequestParam("type") String typeCount,
                                   @RequestParam("infoid") String infoId) {
        if (StrUtil.isNotBlank(typeCount)) {
            if (typeCount.equals("click")) {
                return ExResult.ofAuto(infoUtil.updateInfoClickCount(infoId));
            }

            if (typeCount.equals("read")) {
                return ExResult.ofAuto(infoUtil.updateInfoReadCount(infoId));
            }
        }
        return ExResult.ofFail("更新 " + typeCount + " 错误");
    }

    @GetMapping("detail")
    public ExResult<?> getInfoDetailById(@RequestParam("infoid") String infoId) {
        return ExResult.ofAuto(infoService.getById(infoId));
    }

    @GetMapping("my-info-by-id")
    public ExResult<?> getMyInfoById(@RequestParam("id") String infoId) throws UserException, InfoException {
        UserPlatformEntity currentLoginUserInfo = userUtil.getCurrentLoginUserInfo();
        InfoEntity info = infoService.getById(infoId);
        if (info.getUserId().equals(currentLoginUserInfo.getUserId())) {
            return ExResult.ofSuccess(info);
        } else throw new InfoException("错误!当前信息并不是您发布的信息!,您无权限进行操作");
    }

    @Delete("delete")
    public ExResult<?> deleteInfoById(@RequestParam("id") String infoId) {
        return ExResult.ofAuto(infoService.removeById(infoId));
    }


    @Resource
    private IInfoEntityMapper infomapper;


    @Resource
    private EventUtil eventUtil;

    @GetMapping("test")
    public ExResult<?> Test(@RequestParam("opt") String opt) {
        List<InfoEntity> list = infoService.list();
        if (opt.equals("create"))
            eventUtil.SendInfoAuditEvent(EEventType.EVENT_INFO_CREATE_AUDIT, list.get(2));
        if (opt.equals("update"))
            eventUtil.SendInfoAuditEvent(EEventType.EVENT_INFO_UPDATE_AUDIT, list.get(3));
        return ExResult.ofSuccess("hello");
    }


    /**
     * 获取指定用户的所有信息
     *
     * @param userPlatformId 平台信息编号
     * @return
     */
    @GetMapping("user-info")
    public ExResult<?> getUserInfoByUserPlatformId(@NotBlank(message = "用户平台编号不能为空") @RequestParam("upid") String userPlatformId,
                                                   @RequestParam(value = "current", defaultValue = "1", required = false) long current,
                                                   @RequestParam(value = "size", defaultValue = "20", required = false) long size) throws UserException, InfoException {
        return ExResult.ofAuto(infoUtil.getUserPlatformIdByInfos(current, size, userPlatformId));
    }


    @GetMapping("search")
    public ExResult<?> Search(@RequestParam(value = "current", defaultValue = "1", required = false) long current,
                              @RequestParam(value = "size", defaultValue = "20", required = false) long size,
                              @RequestParam(value = "keyword", defaultValue = "", required = false) String keyword) {
        Page<InfoEntity> page = infoService.page(new Page<>(current, size), new LambdaQueryWrapper<InfoEntity>()
                .func(StrUtil.isNotBlank(keyword.trim()), c -> c.like(InfoEntity::getRemark, keyword.trim()))
                .func(StrUtil.isBlank(keyword.trim()), c -> c.like(InfoEntity::getRemark, keyword.trim()))
                .orderByDesc(InfoEntity::getCreateAt, InfoEntity::getUpdateAt));
        return ExResult.ofAuto(page);
    }


}
